﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using System.Collections;
using AgileShare.Framework.Library.Helpers;
using AgileShare.Framework.Library.Common;

namespace AgileShare.Framework.Library.Managers
{
    public class SettingsManagerBase
    {
        /// <summary>
        /// The SPList that stores the Settings
        /// </summary>
        public SPList ConfigurationList { get; set; }

        /// <summary>
        /// Name of the Key Field of the Config List
        /// </summary>
        public string KeyField { get; set; }

        /// <summary>
        /// Name of the Value field of the Config List
        /// </summary>
        public string ValueField { get; set; }

		/// <summary>
		/// Gets or sets a value indicating whether [use cache].
		/// </summary>
		/// <value>
		///   <c>true</c> if [use cache]; otherwise, <c>false</c>.
		/// </value>
		public bool UseCache { get; set; }

        private int _CacheTime;
        /// <summary>
        /// The number of minutes for which an object should be cached
        /// </summary>
        public int CacheTime { 
            get
            {
                if (_CacheTime == 0) _CacheTime = 360;
                return _CacheTime;
            }
            set { _CacheTime = value; }
        }

		/// <summary>
		/// Get a single configuration value
		/// </summary>
		/// <param name="key">The key value.</param>
		/// <returns>
		/// String that represents the configuration value.
		/// </returns>
        public string GetValue(string key)
        {			
            string retVal = string.Empty;

			if (this.UseCache)
			{
				retVal = GetCachedValue(key);
			}
			else
			{
				retVal = GetNonCachedValue(key);
			}
            return retVal;
        }

		private string GetNonCachedValue(string key)
		{
			string retVal = string.Empty;
			SPList list = ConfigurationList;
			if (list != null)
			{
				SPQuery query = new SPQuery();
				query.Query = string.Format("<Where><Eq><FieldRef Name='{0}' /><Value Type='Text'>{1}</Value></Eq></Where><OrderBy><FieldRef Ascending='False' Name='Modified' /></OrderBy>", KeyField, key);

				var value = list.GetItems(query).Cast<SPListItem>()
								.Where(item => SPListItemHelper.HasField(item, this.ValueField, Constants.SPFieldNameVariation.Title) && item[this.ValueField] != null)
								.Select(item => item[this.ValueField].ToString())
								.FirstOrDefault();

				if (!string.IsNullOrEmpty(value))
				{
					retVal = value;
				}
			}
			return retVal;
		}

        /// <summary>
        /// Returns a value from the cache or from the list and caches it for future use.
        /// </summary>
        /// <param name="key">The Key of the list item whose value should be returned</param>
        /// <returns>String containing the configuration value.</returns>
        private string GetCachedValue(string key)
        {
            string retVal = string.Empty;
            System.Web.Caching.Cache appCache = System.Web.HttpContext.Current.Cache;
            
            string CacheKey = ConfigurationList.ID.ToString();
            Hashtable ht;
            object CachedHash = appCache.Get(CacheKey);
            if (CachedHash == null) 
            {
                ht = new Hashtable();
                appCache.Add(CacheKey, ht, null, DateTime.Now.AddMinutes(CacheTime), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
            } else {
                ht = (Hashtable)CachedHash; 
            }

            if (ht.ContainsKey(key))
            {
                retVal = ht[key].ToString();
            }
            else
            {
                retVal = GetNonCachedValue(key);
                ht[key] = retVal;
                appCache.Insert(CacheKey, ht);
            }

            return retVal;
        }

		/// <summary>
		/// Sets the value.
		/// </summary>
		/// <param name="key">The key.</param>
		/// <param name="value">The value.</param>
        public void SetValue(string key, string value)
        {
            SPList list = ConfigurationList;
            if (list != null)
            {
                SPQuery query = new SPQuery();
                query.Query = string.Format("<Where><Eq><FieldRef Name='{0}' /><Value Type='Text'>{1}</Value></Eq></Where><OrderBy><FieldRef Ascending='False' Name='Modified' /></OrderBy>", KeyField, key);
                SPListItemCollection values = list.GetItems(query);
                if (values.Count > 0)
                {
                    foreach (SPListItem item in values)
                    {
                        item[ValueField] = value;
                        item.Update();
                    }
                }
                else
                {
                    SPListItem newItem = list.Items.Add();
                    newItem[KeyField] = key;
                    newItem[ValueField] = value;
                    newItem.Update();
                }
            }
        }

        /// <summary>
        /// Return an array of Config Values
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public string[] GetValues(string[] keys)
        {
            string[] retVal = new string[keys.Length];

            for (int i = 0; i < keys.Length; i++)
            {
                retVal[i] = GetValue(keys[i]);
            }

            return retVal;
        }
    }
}
